package com.fenghongzhang.module_home.widget

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.widget.OverScroller
import androidx.appcompat.widget.AppCompatImageView
import java.io.IOException
import java.io.InputStream

class BigImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private var decoder: BitmapRegionDecoder? = null
    private var imageWidth = 1
    private var imageHeight = 1
    private var viewWidth = 0
    private var viewHeight = 0
    private var currentScale = 1f
    private var minScale = 1f
    private var maxScale = 5f
    private val currentRect = Rect()
    private val matrix = Matrix()
    private val tempRect = RectF()
    private val gestureDetector: GestureDetector
    private val scaleGestureDetector: ScaleGestureDetector
    private var scroller: OverScroller = OverScroller(context)
    private val flingRunner = FlingRunner()

    private var bitmap: Bitmap? = null
    private var bitmapOptions: BitmapFactory.Options? = null

    init {
        // 初始化手势检测器
        gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
            override fun onDown(e: MotionEvent): Boolean = true

            override fun onScroll(
                e1: MotionEvent?,
                e2: MotionEvent,
                distanceX: Float,
                distanceY: Float
            ): Boolean {
                scrollBy(distanceX.toInt(), distanceY.toInt())
                return true
            }

            override fun onFling(
                e1: MotionEvent?,
                e2: MotionEvent,
                velocityX: Float,
                velocityY: Float
            ): Boolean {
                scroller.fling(
                    currentRect.left,
                    currentRect.top,
                    velocityX.toInt(),
                    velocityY.toInt(),
                    0,
                    imageWidth - currentRect.width(),
                    0,
                    imageHeight - currentRect.height()
                )
                post(flingRunner)
                return true
            }
        })

        // 初始化缩放检测器
        scaleGestureDetector = ScaleGestureDetector(context, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
            override fun onScale(detector: ScaleGestureDetector): Boolean {
                val scale = currentScale * detector.scaleFactor
                currentScale = scale.coerceIn(minScale, maxScale)
                updateRect()
                invalidate()
                return true
            }
        })

        // 初始化滚动器
        scroller = OverScroller(context)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        viewWidth = w
        viewHeight = h
        updateRect()
    }

    fun setInputStream(inputStream: InputStream) {
        try {
            // 初始化解码器
            decoder = BitmapRegionDecoder.newInstance(inputStream, false)
            bitmapOptions = BitmapFactory.Options().apply {
                inPreferredConfig = Bitmap.Config.RGB_565
            }

            // 获取图片原始尺寸
            imageWidth = decoder?.width ?: 0
            imageHeight = decoder?.height ?: 0

            // 计算最小缩放比例
            minScale = minOf(
                viewWidth.toFloat() / imageWidth,
                viewHeight.toFloat() / imageHeight
            ).coerceAtMost(1f)
            currentScale = minScale

            updateRect()
            requestLayout()
            invalidate()
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            inputStream.close()
        }
    }

    private fun updateRect() {
        if (imageWidth == 0 || imageHeight == 0 || viewWidth == 0 || viewHeight == 0) return

        // 计算当前应该显示的矩形区域
        val scaledWidth = (viewWidth / currentScale).toInt()
        val scaledHeight = (viewHeight / currentScale).toInt()

        // 确保不越界
        var left = currentRect.left.coerceIn(0, imageWidth - scaledWidth)
        var top = currentRect.top.coerceIn(0, imageHeight - scaledHeight)

        // 如果图片比视图小，则居中显示
        if (imageWidth < scaledWidth) {
            left = (imageWidth - scaledWidth) / 2
        }
        if (imageHeight < scaledHeight) {
            top = (imageHeight - scaledHeight) / 2
        }

        currentRect.set(left, top, left + scaledWidth, top + scaledHeight)

        // 解码当前区域
        decodeRegion()
    }

    private fun decodeRegion() {
        if (decoder == null || currentRect.isEmpty) return

        // 回收之前的bitmap
        bitmap?.recycle()

        try {
            // 解码指定区域
            bitmap = decoder?.decodeRegion(currentRect, bitmapOptions)
            setImageBitmap(bitmap)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onDraw(canvas: Canvas) {
        if (bitmap == null) {
            super.onDraw(canvas)
            return
        }

        // 计算缩放和平移
        matrix.reset()
        val scale = currentScale
        matrix.postScale(scale, scale)

        // 绘制解码的区域
        canvas.drawBitmap(bitmap!!, matrix, null)
    }

    override fun scrollBy(x: Int, y: Int) {
        if (decoder == null) return

        currentRect.offset(-x, -y)
        updateRect()
        invalidate()
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        scaleGestureDetector.onTouchEvent(event)
        if (!scaleGestureDetector.isInProgress) {
            gestureDetector.onTouchEvent(event)
        }
        return true
    }

    private inner class FlingRunner : Runnable {
        override fun run() {
            if (scroller.computeScrollOffset()) {
                scrollTo(scroller.currX, scroller.currY)
                post(this)
            }
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        // 释放资源
        decoder?.recycle()
        bitmap?.recycle()
        decoder = null
        bitmap = null
    }
}